﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using MoneyManagerNET.Model;

namespace MoneyManagerNET.DAL.Mock
{
    public class EntityBus:IEntityBus
    {
        static TraceSource trace = new TraceSource("Model");

        List<Model.ITransaction> transactions = new List<Model.ITransaction>();
        List<Model.ISubCategory> subcategories = new List<Model.ISubCategory>();
        List<Model.ICategory> categories = new List<Model.ICategory>();
        List<Model.IStockInvestment> stockInvestments = new List<Model.IStockInvestment>();
        List<Model.IStockAccount> stockAccounts = new List<Model.IStockAccount>();
        List<Model.ICurrency> currencies = new List<Model.ICurrency>();
        List<Model.IContragent> contragents = new List<Model.IContragent>();
        List<Model.IBankAccount> bankAccounts = new List<Model.IBankAccount>();
        List<Model.IAccount> accounts = new List<Model.IAccount>();
        List<Model.IAsset> assets = new List<IAsset>();

        public EntityBus()
        {
            var cat = new Category();
            cat.Name = "food";
            categories.Add(cat);

            var scat = new SubCategory();
            scat.Name = "restaurant";
            scat.Category = cat;
            subcategories.Add(scat);


            categories.Add(new Category(){Name="Taxes"});
            categories.Add(new Category() { Name = "Transportation" });

            var acc1 = new BankAccount();
            acc1.Name = "purse";
            acc1.Balance = 850;
            bankAccounts.Add(acc1);

            var acc2 =new BankAccount();
            acc2.Name = "saving";
            acc2.Balance = 5000;
            bankAccounts.Add(acc2);


            ITransaction tr = new Transaction();
            tr.FromAccount = acc1;
            tr.Amount = 230;
            tr.Category = cat;
            tr.SubCategory = scat;
            tr.Date = DateTime.Now;
            var neighbour = new Contragent() { Name = "neighbour" };
            tr.Contragent = neighbour;            
            transactions.Add(tr);

            ITransaction tr2 = new Transaction();
            tr2.FromAccount = acc2;
            tr2.ToAccount = acc1;
            tr2.Amount = 506;
            tr2.Category = cat;
            tr2.SubCategory = scat;
            tr2.Date = DateTime.Now;
            transactions.Add(tr2);

            var stock1 = new StockAccount();
            stock1.Name = "NASDAQ";
             
            stock1.Balance = 240;
            stockAccounts.Add(stock1);

            var investment=new StockInvestment() { Commission = 12, CurrentPrice = 200, Date = DateTime.Today.AddMonths(-2), HeldAt = stock1, Notes = "thought will be profitable", PurchasePrice = 120, StockName = "Neft", StockSymbol = "AZL", StockCount = 320 };
            stockInvestments.Add(investment);

            var stock2 = new StockAccount();
            stock2.Name = "MICROSOFT";
            stock2.Balance = 560;
            stockAccounts.Add(stock2);


            contragents.Add(new Contragent() { Name="Government"});
            contragents.Add(new Contragent() { Name = "McDonalds" });
            contragents.Add(new Contragent() { Name = "Emlpoyer" });
            contragents.Add(new Contragent() { Name = "SuperMarket" });
            contragents.Add(neighbour);


            Asset a1 = new Asset();
            a1.AssetType = 1;
            a1.ChangeInValue = 1;
            a1.Date = DateTime.Now.AddMonths(-18);
            a1.Name = "my asset";
            a1.Rate = 0.3;
            a1.Value = 2500;
            assets.Add(a1);
        }


        public IEnumerable<TEntity> Select<TEntity>(Func<TEntity, bool> where) where TEntity : class
        {
            List<TEntity> list = SelectListByType<TEntity>() as List<TEntity>;
            if (where == null)
                return list;
            else
                return list.Where(where);
        }

        private System.Collections.IEnumerable SelectListByType<TEntity>() where TEntity : class
        {
            if (typeof(TEntity) == typeof(Model.ITransaction)) return transactions;
            if (typeof(TEntity) == typeof(Model.ISubCategory)) return subcategories;
            if (typeof(TEntity) == typeof(Model.ICategory)) return categories;
            if (typeof(TEntity) == typeof(Model.IStockInvestment)) return stockInvestments;
            if (typeof(TEntity) == typeof(Model.IStockAccount)) return stockAccounts;
            if (typeof(TEntity) == typeof(Model.ICurrency)) return currencies;
            if (typeof(TEntity) == typeof(Model.IContragent)) return contragents;
            if (typeof(TEntity) == typeof(Model.IBankAccount)) return bankAccounts;
            if (typeof(TEntity) == typeof(Model.IAccount)) return accounts;
            if (typeof(TEntity) == typeof(Model.IAsset)) return assets;

            return null;
        }

        public TEntity New<TEntity>() where TEntity : class
        {
            object instance = CreateByType<TEntity>();
            
            List<TEntity> list = SelectListByType<TEntity>() as List<TEntity>;
            TEntity entity=instance as TEntity;
            list.Add(entity);
            return entity;
        }

        private object CreateByType<TEntity>()
        {
            Type t = null;
            if (typeof(TEntity) == typeof(Model.ITransaction))  t=typeof(Transaction);
            if (typeof(TEntity) == typeof(Model.ISubCategory))  t = typeof(SubCategory);
            if (typeof(TEntity) == typeof(Model.ICategory))  t = typeof(Category);
            if (typeof(TEntity) == typeof(Model.IStockInvestment))  t = typeof(StockInvestment);
            if (typeof(TEntity) == typeof(Model.IStockAccount))  t = typeof(StockAccount);
            if (typeof(TEntity) == typeof(Model.ICurrency))  t = typeof(Currency);
            if (typeof(TEntity) == typeof(Model.IContragent))  t = typeof(Contragent);
            if (typeof(TEntity) == typeof(Model.IBankAccount))  t = typeof(BankAccount);
            if (typeof(TEntity) == typeof(Model.IAccount))  t = typeof(Account);
            if (typeof(TEntity) == typeof(Model.IAsset)) t = typeof(Asset);

            //TODO: add created to list


            if (t != null) 
                return Activator.CreateInstance(t);
            else
                return null;
        }

        public void SaveAll()
        {
            trace.TraceInformation("mock save all");
        }

        public void Reset()
        {
            trace.TraceInformation("mock reset");
        }


        public void Delete<TEntity>(TEntity entity) where TEntity : class
        {
            trace.TraceInformation("mock delete");

            List<TEntity> list = SelectListByType<TEntity>() as List<TEntity>;
            list.Remove(entity);

            object oe=entity;
            if (typeof(TEntity) == typeof(Model.ITransaction))
            {
                Transaction.DeleteEntity((Transaction)oe);
                transactions.Remove((Transaction)oe);
            }
            if (typeof(TEntity) == typeof(Model.ISubCategory))
            {
                SubCategory.DeleteEntity((SubCategory)oe);
                subcategories.Remove((SubCategory)oe);
            }
            if (typeof(TEntity) == typeof(Model.ICategory))
            {
                Category.DeleteEntity((Category)oe);
                categories.Remove((Category)oe);
            }
            if (typeof(TEntity) == typeof(Model.IStockInvestment))
            {
                StockInvestment.DeleteEntity((StockInvestment)oe);
                stockInvestments.Remove((StockInvestment)oe);
            }
            if (typeof(TEntity) == typeof(Model.IStockAccount))
            {
                StockAccount.DeleteEntity((StockAccount)oe);
                stockAccounts.Remove((StockAccount)oe);
            }
            if (typeof(TEntity) == typeof(Model.ICurrency))
            {
                Currency.DeleteEntity((Currency)oe);
                currencies.Remove((Currency)oe);
            }
            if (typeof(TEntity) == typeof(Model.IContragent))
            {
                Contragent.DeleteEntity((Contragent)oe);
                contragents.Remove((Contragent)oe);
            }
            if (typeof(TEntity) == typeof(Model.IBankAccount))
            {
                BankAccount.DeleteEntity((BankAccount)oe);
                bankAccounts.Remove((BankAccount)oe);
            }
            if (typeof(TEntity).IsAssignableFrom( typeof(Model.IAccount) ))
            {
                Account.DeleteEntity((Account)oe);
                accounts.Remove((Account)oe);
            }

        }
    }
}
